<!DOCTYPE html>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#375EAB">

  <title>src/github.com/user/watch/watch.go - Go Documentation Server</title>

<link type="text/css" rel="stylesheet" href="watch.go_files/style.css">

<script>window.initFuncs = [];</script>
<script src="watch.go_files/jquery.js" defer="defer"></script>



<script>var goVersion = "go1.15.3";</script>
<script src="watch.go_files/godocs.js" defer="defer"></script>
</head>
<body>

<div id="lowframe" style="position: fixed; bottom: 0; left: 0; height: 0; width: 100%; border-top: thin solid grey; background-color: white; overflow: auto;">
...
</div><!-- #lowframe -->

<div id="topbar" class="wide"><div class="container">
<div class="top-heading" id="heading-wide"><a href="http://localhost:7070/pkg/">Go Documentation Server</a></div>
<div class="top-heading" id="heading-narrow"><a href="http://localhost:7070/pkg/">GoDoc</a></div>
<a href="#" id="menu-button"><span id="menu-button-arrow">▽</span></a>
<form method="GET" action="/search">
<div id="menu" style="min-width: 60px;">

<span class="search-box"><input type="search" id="search" name="q" placeholder="Search" aria-label="Search" required=""><button type="submit"><span><!-- magnifying glass: --><svg width="24" height="24" viewBox="0 0 24 24"><title>submit search</title><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></button></span>
</div>
</form>

</div></div>



<div id="page" class="wide" style="outline: currentcolor none 0px;" tabindex="-1">
<div class="container">


  <h1>
    Source file
    <a href="http://localhost:7070/src">src</a>/<a href="http://localhost:7070/src/github.com">github.com</a>/<a href="http://localhost:7070/src/github.com/user">user</a>/<a href="http://localhost:7070/src/github.com/user/watch">watch</a>/<span class="text-muted">watch.go</span>
  </h1>





  <h2>
    Documentation: <a href="http://localhost:7070/pkg/github.com/user/watch">github.com/user/watch</a>
  </h2>



<div id="nav"></div>


<script type="text/javascript">document.ANALYSIS_DATA = null;</script>
<pre><span id="L1" class="ln">     1&nbsp;&nbsp;</span>package watch
<span id="L2" class="ln">     2&nbsp;&nbsp;</span>
<span id="L3" class="ln">     3&nbsp;&nbsp;</span>import (
<span id="L4" class="ln">     4&nbsp;&nbsp;</span>	"bufio"
<span id="L5" class="ln">     5&nbsp;&nbsp;</span>	"fmt"
<span id="L6" class="ln">     6&nbsp;&nbsp;</span>	"io"
<span id="L7" class="ln">     7&nbsp;&nbsp;</span>	"os"
<span id="L8" class="ln">     8&nbsp;&nbsp;</span>	"runtime"
<span id="L9" class="ln">     9&nbsp;&nbsp;</span>	"strings"
<span id="L10" class="ln">    10&nbsp;&nbsp;</span>	"time"
<span id="L11" class="ln">    11&nbsp;&nbsp;</span>)
<span id="L12" class="ln">    12&nbsp;&nbsp;</span>
<span id="L13" class="ln">    13&nbsp;&nbsp;</span><span class="comment">//Listener 当文件发生改变时调用的接口</span>
<span id="L14" class="ln">    14&nbsp;&nbsp;</span>type Listener interface {
<span id="L15" class="ln">    15&nbsp;&nbsp;</span>	Listen(Configuration, Configuration)
<span id="L16" class="ln">    16&nbsp;&nbsp;</span>}
<span id="L17" class="ln">    17&nbsp;&nbsp;</span>
<span id="L18" class="ln">    18&nbsp;&nbsp;</span><span class="comment">//errorNews为自定义错误消息</span>
<span id="L19" class="ln">    19&nbsp;&nbsp;</span>type errorNews string
<span id="L20" class="ln">    20&nbsp;&nbsp;</span>
<span id="L21" class="ln">    21&nbsp;&nbsp;</span><span class="comment">//Configuration 储存读取ini文件得到的信息</span>
<span id="L22" class="ln">    22&nbsp;&nbsp;</span>type Configuration struct {
<span id="L23" class="ln">    23&nbsp;&nbsp;</span>	name       string
<span id="L24" class="ln">    24&nbsp;&nbsp;</span>	section    map[string]*Section
<span id="L25" class="ln">    25&nbsp;&nbsp;</span>	sectionNum int
<span id="L26" class="ln">    26&nbsp;&nbsp;</span>}
<span id="L27" class="ln">    27&nbsp;&nbsp;</span>
<span id="L28" class="ln">    28&nbsp;&nbsp;</span>var (
<span id="L29" class="ln">    29&nbsp;&nbsp;</span>	<span class="comment">//LineBreak 换行符号</span>
<span id="L30" class="ln">    30&nbsp;&nbsp;</span>	LineBreak byte = '\n'
<span id="L31" class="ln">    31&nbsp;&nbsp;</span>
<span id="L32" class="ln">    32&nbsp;&nbsp;</span>	<span class="comment">//CommentSign ini配置文件中注释符号</span>
<span id="L33" class="ln">    33&nbsp;&nbsp;</span>	<span class="comment">//Linus: #, Windows: ;</span>
<span id="L34" class="ln">    34&nbsp;&nbsp;</span>	CommentSign byte = '#'
<span id="L35" class="ln">    35&nbsp;&nbsp;</span>)
<span id="L36" class="ln">    36&nbsp;&nbsp;</span>
<span id="L37" class="ln">    37&nbsp;&nbsp;</span>func init() {
<span id="L38" class="ln">    38&nbsp;&nbsp;</span>	if runtime.GOOS == "windows" {
<span id="L39" class="ln">    39&nbsp;&nbsp;</span>		CommentSign = ';'
<span id="L40" class="ln">    40&nbsp;&nbsp;</span>	}
<span id="L41" class="ln">    41&nbsp;&nbsp;</span>}
<span id="L42" class="ln">    42&nbsp;&nbsp;</span>
<span id="L43" class="ln">    43&nbsp;&nbsp;</span>func (err errorNews) Error() string {
<span id="L44" class="ln">    44&nbsp;&nbsp;</span>	return fmt.Sprintf(string(err))
<span id="L45" class="ln">    45&nbsp;&nbsp;</span>}
<span id="L46" class="ln">    46&nbsp;&nbsp;</span>
<span id="L47" class="ln">    47&nbsp;&nbsp;</span><span class="comment">//GetSectionNum 返回Configuration类型中的section字段数目</span>
<span id="L48" class="ln">    48&nbsp;&nbsp;</span>func (Conf Configuration) GetSectionNum() int {
<span id="L49" class="ln">    49&nbsp;&nbsp;</span>	return Conf.sectionNum
<span id="L50" class="ln">    50&nbsp;&nbsp;</span>}
<span id="L51" class="ln">    51&nbsp;&nbsp;</span>
<span id="L52" class="ln">    52&nbsp;&nbsp;</span><span class="comment">//GetSection 返回Configuration类型中的section</span>
<span id="L53" class="ln">    53&nbsp;&nbsp;</span>func (Conf Configuration) GetSection() map[string]*Section {
<span id="L54" class="ln">    54&nbsp;&nbsp;</span>	NewSection := make(map[string]*Section)
<span id="L55" class="ln">    55&nbsp;&nbsp;</span>	for sectionKey, section := range Conf.section {
<span id="L56" class="ln">    56&nbsp;&nbsp;</span>		NewSection[sectionKey] = &amp;Section{make(map[string]string), 0}
<span id="L57" class="ln">    57&nbsp;&nbsp;</span>		for key, value := range section.key {
<span id="L58" class="ln">    58&nbsp;&nbsp;</span>			NewSection[sectionKey].key[key] = value
<span id="L59" class="ln">    59&nbsp;&nbsp;</span>		}
<span id="L60" class="ln">    60&nbsp;&nbsp;</span>		NewSection[sectionKey].keyNum = section.keyNum
<span id="L61" class="ln">    61&nbsp;&nbsp;</span>	}
<span id="L62" class="ln">    62&nbsp;&nbsp;</span>	return NewSection
<span id="L63" class="ln">    63&nbsp;&nbsp;</span>}
<span id="L64" class="ln">    64&nbsp;&nbsp;</span>
<span id="L65" class="ln">    65&nbsp;&nbsp;</span><span class="comment">//GetKey 返回字段为section的key</span>
<span id="L66" class="ln">    66&nbsp;&nbsp;</span>func (Conf Configuration) GetKey(section string) *Section {
<span id="L67" class="ln">    67&nbsp;&nbsp;</span>	return Conf.section[section]
<span id="L68" class="ln">    68&nbsp;&nbsp;</span>}
<span id="L69" class="ln">    69&nbsp;&nbsp;</span>
<span id="L70" class="ln">    70&nbsp;&nbsp;</span><span class="comment">//ExistSection 判断Section是否已经存在于Configuration.section中</span>
<span id="L71" class="ln">    71&nbsp;&nbsp;</span>func (Conf Configuration) ExistSection(section string) bool {
<span id="L72" class="ln">    72&nbsp;&nbsp;</span>	_, exist := Conf.section[section]
<span id="L73" class="ln">    73&nbsp;&nbsp;</span>	return exist
<span id="L74" class="ln">    74&nbsp;&nbsp;</span>}
<span id="L75" class="ln">    75&nbsp;&nbsp;</span>
<span id="L76" class="ln">    76&nbsp;&nbsp;</span><span class="comment">//CreateConfiguration 创建Configuration类型数据并返回</span>
<span id="L77" class="ln">    77&nbsp;&nbsp;</span><span class="selection">func CreateConfiguration(filename string) Configuration</span> {
<span id="L78" class="ln">    78&nbsp;&nbsp;</span>	return Configuration{
<span id="L79" class="ln">    79&nbsp;&nbsp;</span>		name:       filename,
<span id="L80" class="ln">    80&nbsp;&nbsp;</span>		section:    make(map[string]*Section),
<span id="L81" class="ln">    81&nbsp;&nbsp;</span>		sectionNum: 0,
<span id="L82" class="ln">    82&nbsp;&nbsp;</span>	}
<span id="L83" class="ln">    83&nbsp;&nbsp;</span>}
<span id="L84" class="ln">    84&nbsp;&nbsp;</span>
<span id="L85" class="ln">    85&nbsp;&nbsp;</span><span class="comment">//OpneFile 打开并读取ini文件</span>
<span id="L86" class="ln">    86&nbsp;&nbsp;</span>func OpneFile(filename string) (Configuration, error) {
<span id="L87" class="ln">    87&nbsp;&nbsp;</span>	<span class="comment">//初始化变量</span>
<span id="L88" class="ln">    88&nbsp;&nbsp;</span>	Conf := CreateConfiguration(filename)
<span id="L89" class="ln">    89&nbsp;&nbsp;</span>
<span id="L90" class="ln">    90&nbsp;&nbsp;</span>	<span class="comment">//自定义错误</span>
<span id="L91" class="ln">    91&nbsp;&nbsp;</span>	var errorNew errorNews
<span id="L92" class="ln">    92&nbsp;&nbsp;</span>
<span id="L93" class="ln">    93&nbsp;&nbsp;</span>	<span class="comment">//打开文件</span>
<span id="L94" class="ln">    94&nbsp;&nbsp;</span>	file, err := os.Open(filename)
<span id="L95" class="ln">    95&nbsp;&nbsp;</span>	if err != nil {
<span id="L96" class="ln">    96&nbsp;&nbsp;</span>		errorNew = "The file does not exist!"
<span id="L97" class="ln">    97&nbsp;&nbsp;</span>		return Conf, errorNew
<span id="L98" class="ln">    98&nbsp;&nbsp;</span>	}
<span id="L99" class="ln">    99&nbsp;&nbsp;</span>	defer file.Close()
<span id="L100" class="ln">   100&nbsp;&nbsp;</span>
<span id="L101" class="ln">   101&nbsp;&nbsp;</span>	buffer := bufio.NewReader(file)
<span id="L102" class="ln">   102&nbsp;&nbsp;</span>
<span id="L103" class="ln">   103&nbsp;&nbsp;</span>	<span class="comment">//key当前所属字段，默认为空</span>
<span id="L104" class="ln">   104&nbsp;&nbsp;</span>	section := ""
<span id="L105" class="ln">   105&nbsp;&nbsp;</span>	Conf.section[section] = &amp;Section{key: make(map[string]string), keyNum: 0}
<span id="L106" class="ln">   106&nbsp;&nbsp;</span>	Conf.sectionNum++
<span id="L107" class="ln">   107&nbsp;&nbsp;</span>	for {
<span id="L108" class="ln">   108&nbsp;&nbsp;</span>		flag := 0
<span id="L109" class="ln">   109&nbsp;&nbsp;</span>		line, err := buffer.ReadString(LineBreak)
<span id="L110" class="ln">   110&nbsp;&nbsp;</span>
<span id="L111" class="ln">   111&nbsp;&nbsp;</span>		if err == io.EOF {
<span id="L112" class="ln">   112&nbsp;&nbsp;</span>			flag = 1
<span id="L113" class="ln">   113&nbsp;&nbsp;</span>		} else if err != nil {
<span id="L114" class="ln">   114&nbsp;&nbsp;</span>			errorNew = "There was an error reading the file！"
<span id="L115" class="ln">   115&nbsp;&nbsp;</span>			return Conf, errorNew
<span id="L116" class="ln">   116&nbsp;&nbsp;</span>		}
<span id="L117" class="ln">   117&nbsp;&nbsp;</span>
<span id="L118" class="ln">   118&nbsp;&nbsp;</span>		if line == "" || line[0] == CommentSign {
<span id="L119" class="ln">   119&nbsp;&nbsp;</span>			if flag == 1 {
<span id="L120" class="ln">   120&nbsp;&nbsp;</span>				break
<span id="L121" class="ln">   121&nbsp;&nbsp;</span>			} else {
<span id="L122" class="ln">   122&nbsp;&nbsp;</span>				continue
<span id="L123" class="ln">   123&nbsp;&nbsp;</span>			}
<span id="L124" class="ln">   124&nbsp;&nbsp;</span>		} else if line[0] == '[' {
<span id="L125" class="ln">   125&nbsp;&nbsp;</span>			section = line[1 : len(line)-2]
<span id="L126" class="ln">   126&nbsp;&nbsp;</span>
<span id="L127" class="ln">   127&nbsp;&nbsp;</span>			<span class="comment">//判断是否已经读取过同样的字段</span>
<span id="L128" class="ln">   128&nbsp;&nbsp;</span>			if !Conf.ExistSection(section) {
<span id="L129" class="ln">   129&nbsp;&nbsp;</span>				Conf.section[section] = &amp;Section{make(map[string]string), 0}
<span id="L130" class="ln">   130&nbsp;&nbsp;</span>				Conf.sectionNum++
<span id="L131" class="ln">   131&nbsp;&nbsp;</span>			}
<span id="L132" class="ln">   132&nbsp;&nbsp;</span>		} else {
<span id="L133" class="ln">   133&nbsp;&nbsp;</span>			for i := 0; i &lt; len(line); i++ {
<span id="L134" class="ln">   134&nbsp;&nbsp;</span>				if line[i] == '=' {
<span id="L135" class="ln">   135&nbsp;&nbsp;</span>					key := strings.Replace(line[0:i], " ", "", -1)
<span id="L136" class="ln">   136&nbsp;&nbsp;</span>					value := strings.Replace(line[i+1:], " ", "", -1)
<span id="L137" class="ln">   137&nbsp;&nbsp;</span>					value = strings.Replace(value, "\n", "", -1)
<span id="L138" class="ln">   138&nbsp;&nbsp;</span>					Conf.GetKey(section).key[key] = value
<span id="L139" class="ln">   139&nbsp;&nbsp;</span>					Conf.GetKey(section).keyNum++
<span id="L140" class="ln">   140&nbsp;&nbsp;</span>					break
<span id="L141" class="ln">   141&nbsp;&nbsp;</span>				}
<span id="L142" class="ln">   142&nbsp;&nbsp;</span>			}
<span id="L143" class="ln">   143&nbsp;&nbsp;</span>		}
<span id="L144" class="ln">   144&nbsp;&nbsp;</span>
<span id="L145" class="ln">   145&nbsp;&nbsp;</span>		if flag == 1 {
<span id="L146" class="ln">   146&nbsp;&nbsp;</span>			break
<span id="L147" class="ln">   147&nbsp;&nbsp;</span>		}
<span id="L148" class="ln">   148&nbsp;&nbsp;</span>	}
<span id="L149" class="ln">   149&nbsp;&nbsp;</span>	return Conf, nil
<span id="L150" class="ln">   150&nbsp;&nbsp;</span>}
<span id="L151" class="ln">   151&nbsp;&nbsp;</span>
<span id="L152" class="ln">   152&nbsp;&nbsp;</span><span class="comment">//PrintConf 打印配置信息</span>
<span id="L153" class="ln">   153&nbsp;&nbsp;</span>func PrintConf(conf Configuration) {
<span id="L154" class="ln">   154&nbsp;&nbsp;</span>	for section, key1 := range conf.section {
<span id="L155" class="ln">   155&nbsp;&nbsp;</span>		fmt.Printf("[%s]\n", section)
<span id="L156" class="ln">   156&nbsp;&nbsp;</span>		for key2, value := range key1.key {
<span id="L157" class="ln">   157&nbsp;&nbsp;</span>			fmt.Printf("%s = %s\n", key2, value)
<span id="L158" class="ln">   158&nbsp;&nbsp;</span>		}
<span id="L159" class="ln">   159&nbsp;&nbsp;</span>		fmt.Printf("\n")
<span id="L160" class="ln">   160&nbsp;&nbsp;</span>	}
<span id="L161" class="ln">   161&nbsp;&nbsp;</span>}
<span id="L162" class="ln">   162&nbsp;&nbsp;</span>
<span id="L163" class="ln">   163&nbsp;&nbsp;</span><span class="comment">//ListenFunc 监听文件并调用相应方法</span>
<span id="L164" class="ln">   164&nbsp;&nbsp;</span>func ListenFunc(filename string, listener Listener, Conf Configuration) {
<span id="L165" class="ln">   165&nbsp;&nbsp;</span>	for {
<span id="L166" class="ln">   166&nbsp;&nbsp;</span>		NewConf, err := OpneFile(filename)
<span id="L167" class="ln">   167&nbsp;&nbsp;</span>		if err != nil {
<span id="L168" class="ln">   168&nbsp;&nbsp;</span>			fmt.Println(err)
<span id="L169" class="ln">   169&nbsp;&nbsp;</span>			return
<span id="L170" class="ln">   170&nbsp;&nbsp;</span>		}
<span id="L171" class="ln">   171&nbsp;&nbsp;</span>
<span id="L172" class="ln">   172&nbsp;&nbsp;</span>		<span class="comment">//判断配置文件中属性是否发生变化</span>
<span id="L173" class="ln">   173&nbsp;&nbsp;</span>		if Conf.sectionNum != NewConf.sectionNum {
<span id="L174" class="ln">   174&nbsp;&nbsp;</span>			listener.Listen(Conf, NewConf)
<span id="L175" class="ln">   175&nbsp;&nbsp;</span>			Conf = NewConf
<span id="L176" class="ln">   176&nbsp;&nbsp;</span>			return
<span id="L177" class="ln">   177&nbsp;&nbsp;</span>		}
<span id="L178" class="ln">   178&nbsp;&nbsp;</span>		for keySection, section := range Conf.section {
<span id="L179" class="ln">   179&nbsp;&nbsp;</span>			if !NewConf.ExistSection(keySection) {
<span id="L180" class="ln">   180&nbsp;&nbsp;</span>				listener.Listen(Conf, NewConf)
<span id="L181" class="ln">   181&nbsp;&nbsp;</span>				Conf = NewConf
<span id="L182" class="ln">   182&nbsp;&nbsp;</span>				return
<span id="L183" class="ln">   183&nbsp;&nbsp;</span>			}
<span id="L184" class="ln">   184&nbsp;&nbsp;</span>			NewSection := NewConf.GetKey(keySection)
<span id="L185" class="ln">   185&nbsp;&nbsp;</span>			if section.keyNum != NewSection.keyNum {
<span id="L186" class="ln">   186&nbsp;&nbsp;</span>				listener.Listen(Conf, NewConf)
<span id="L187" class="ln">   187&nbsp;&nbsp;</span>				Conf = NewConf
<span id="L188" class="ln">   188&nbsp;&nbsp;</span>				return
<span id="L189" class="ln">   189&nbsp;&nbsp;</span>			}
<span id="L190" class="ln">   190&nbsp;&nbsp;</span>
<span id="L191" class="ln">   191&nbsp;&nbsp;</span>			for key, value := range section.key {
<span id="L192" class="ln">   192&nbsp;&nbsp;</span>				if !NewSection.ExistKey(key) || value != NewSection.GetValue(key) {
<span id="L193" class="ln">   193&nbsp;&nbsp;</span>					listener.Listen(Conf, NewConf)
<span id="L194" class="ln">   194&nbsp;&nbsp;</span>					Conf = NewConf
<span id="L195" class="ln">   195&nbsp;&nbsp;</span>					return
<span id="L196" class="ln">   196&nbsp;&nbsp;</span>				}
<span id="L197" class="ln">   197&nbsp;&nbsp;</span>			}
<span id="L198" class="ln">   198&nbsp;&nbsp;</span>		}
<span id="L199" class="ln">   199&nbsp;&nbsp;</span>
<span id="L200" class="ln">   200&nbsp;&nbsp;</span>		time.Sleep(time.Duration(1) * time.Second)
<span id="L201" class="ln">   201&nbsp;&nbsp;</span>	}
<span id="L202" class="ln">   202&nbsp;&nbsp;</span>}
<span id="L203" class="ln">   203&nbsp;&nbsp;</span>
<span id="L204" class="ln">   204&nbsp;&nbsp;</span><span class="comment">//Watch 读取文件并监听</span>
<span id="L205" class="ln">   205&nbsp;&nbsp;</span>func Watch(filename string, listener Listener) (Configuration, error) {
<span id="L206" class="ln">   206&nbsp;&nbsp;</span>
<span id="L207" class="ln">   207&nbsp;&nbsp;</span>	Conf, err := OpneFile(filename)
<span id="L208" class="ln">   208&nbsp;&nbsp;</span>	if err != nil {
<span id="L209" class="ln">   209&nbsp;&nbsp;</span>		fmt.Println(err)
<span id="L210" class="ln">   210&nbsp;&nbsp;</span>		return Conf, err
<span id="L211" class="ln">   211&nbsp;&nbsp;</span>	}
<span id="L212" class="ln">   212&nbsp;&nbsp;</span>
<span id="L213" class="ln">   213&nbsp;&nbsp;</span>	PrintConf(Conf)
<span id="L214" class="ln">   214&nbsp;&nbsp;</span>
<span id="L215" class="ln">   215&nbsp;&nbsp;</span>	<span class="comment">//开始监听文件,当文件发生改变时调用Listen方法</span>
<span id="L216" class="ln">   216&nbsp;&nbsp;</span>	fmt.Println("Listening...")
<span id="L217" class="ln">   217&nbsp;&nbsp;</span>	ListenFunc(filename, listener, Conf)
<span id="L218" class="ln">   218&nbsp;&nbsp;</span>
<span id="L219" class="ln">   219&nbsp;&nbsp;</span>	return Conf, nil
<span id="L220" class="ln">   220&nbsp;&nbsp;</span>}
<span id="L221" class="ln">   221&nbsp;&nbsp;</span>
</pre><p><a href="http://localhost:7070/src/github.com/user/watch/watch.go?m=text">View as plain text</a></p>

<div id="footer">
Build version go1.15.3.<br>
Except as <a href="https://developers.google.com/site-policies#restrictions">noted</a>,
the content of this page is licensed under the
Creative Commons Attribution 3.0 License,
and code is licensed under a <a href="http://localhost:7070/LICENSE">BSD license</a>.<br>
<a href="http://localhost:7070/doc/tos.html">Terms of Service</a> |
<a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
</div>

</div><!-- .container -->
</div><!-- #page -->


</body></html>